#ifndef _ARM_H
#define _ARM_H

#ifndef __ASSEMBLY__
#include <types.h>
#endif

#define CPU_ARCH_UNKNOWN    0
#define CPU_ARCH_ARMv3      1
#define CPU_ARCH_ARMv4      2
#define CPU_ARCH_ARMv4T     3
#define CPU_ARCH_ARMv5      4
#define CPU_ARCH_ARMv5T     5
#define CPU_ARCH_ARMv5TE    6
#define CPU_ARCH_ARMv5TEJ   7
#define CPU_ARCH_ARMv6      8
#define CPU_ARCH_ARMv7      9

/* PSR */

#define ARM_MODE_USR  0x10
#define ARM_MODE_FIQ  0x11
#define ARM_MODE_IRQ  0x12
#define ARM_MODE_SVC  0x13
#define ARM_MODE_ABT  0x17
#define ARM_MODE_UND  0x1b
#define ARM_MODE_SYS  0x1f
#define ARM_MODE_MASK 0x1f

#define ARM_FIQ_MASK  (1 << 6)
#define ARM_IRQ_MASK  (1 << 7)
#define ARM_INT_MASK  (ARM_IRQ_MASK | ARM_FIQ_MASK)

/* CP15 */

/* c0 - cpuid register */

#ifndef __ASSEMBLY__ 

static inline uint32_t get_cpuid_id(void)
{
	uint32_t val;

	asm ("mrc p15, 0, %0, c0, c0, 0"
		: "=r" (val)
		: );
    return val;
}

static inline uint32_t get_cpuid_cachetype(void)
{
	uint32_t val;

	asm ("mrc p15, 0, %0, c0, c0, 1"
		: "=r" (val)
		: );
	return val;
}

#endif 

/* c1 - control register */

#define CR_M    (1 << 0)    /* MMU enable						*/
#define CR_A    (1 << 1)    /* Alignment abort enable			*/
#define CR_C    (1 << 2)    /* Dcache enable					*/
#define CR_B    (1 << 7)    /* Big endian						*/
#define CR_S    (1 << 8)    /* System MMU protection			*/
#define CR_R    (1 << 9)    /* ROM MMU protection				*/
#define CR_I    (1 << 12)   /* Icache enable					*/
#define CR_V    (1 << 13)   /* Vectors relocated to 0xffff0000  */
#define CR_RR   (1 << 14)   /* Round Robin cache replacement    */
#define CR_NF   (1 << 30)   /* notFastBus select				*/
#define CR_IA	(1 << 31)	/* Asynchronous clock select		*/

#ifndef __ASSEMBLY__ 

static inline uint32_t get_cr(void)
{
    uint32_t val;

    asm ("mrc p15, 0, %0, c1, c0, 0"
		: "=r" (val) 
		: );
#if (CPU_ARCH == CPU_ARCH_ARMv4T)
    return (val & ~(0x7fff << 15));
#else
	return val;
#endif
}

static inline void set_cr(uint32_t val)
{
    asm ("mcr p15, 0, %0, c1, c0, 0" 
		: 
		: "r" (val));
}

#endif

/*c2 - translation table base register */

#ifndef __ASSEMBLY__ 

static inline void set_ttb(uint32_t val) 
{
	asm("mcr p15, 0, %0, c2, c0, 0"
		:
		: "r" (val));
}

static inline uint32_t get_ttb(void)
{
	uint32_t val;									

	asm("mrc p15, 0, %0, c2, c0, 0"					
		: "=r" (val)									
		: );										
	return val;
}

#endif 

/* c3 - domain access control register */

#ifndef __ASSEMBLY__

static inline void set_dac(uint32_t val)
{
	asm("mcr p15, 0, %0, c3, c0, 0"
		:
		: "r" (val));
}

static inline uint32_t get_dac(void)
{
	uint32_t val;

	asm("mrc p15, 0, %0, c3, c0, 0"	
			: "=r" (val)
			: );
	return val;
}

#endif 

#ifndef __ASSEMBLY__ 
int get_cpu_architecture(void);
#endif 

#endif /* _ARM_H */

